<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="应用名称" prop="name">
        <el-input
            v-model="queryParams.name"
            placeholder="请输入应用名称"
            clearable
            @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="模型编码" prop="modelCode">
        <el-input
            v-model="queryParams.modelCode"
            placeholder="请输入模型编码"
            clearable
            @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="状态" prop="status">
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
          <el-option
              v-for="dict in ai_apps_status"
              :key="dict.value"
              :label="dict.label"
              :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
            type="primary"
            plain
            icon="Plus"
            @click="handleAdd"
            v-hasPermi="['ai:aiApps:add']"
        >新增
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
            type="danger"
            plain
            icon="Delete"
            :disabled="multiple"
            @click="handleDelete"
            v-hasPermi="['ai:aiApps:remove']"
        >删除
        </el-button>
      </el-col>
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="aiAppsList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center"/>
      <el-table-column label="ID" align="center" prop="id"/>
      <el-table-column label="应用图标" align="center" prop="imgUrl" width="100">
        <template #default="scope">
          <image-preview :src="scope.row.imgUrl" :width="50" :height="50"/>
        </template>
      </el-table-column>
      <el-table-column label="应用名称" align="center" prop="name" show-overflow-tooltip/>
      <el-table-column label="模型名称" align="center" show-overflow-tooltip>
        <template #default="scope">
          {{ getModelName(scope.row.modelId) }}
        </template>
      </el-table-column>
      <el-table-column label="状态" align="center" prop="status">
        <template #default="scope">
          <dict-tag :options="ai_apps_status" :value="scope.row.status"/>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="View" @click="handleDetail(scope.row)">详情</el-button>
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['ai:aiApps:edit']"
                     v-show="scope.row.status !== 1">修改
          </el-button>
          <el-button link type="primary" icon="CircleCloseFilled" @click="handleStatus(scope.row)" v-hasPermi="['ai:aiApps:stop']"
                     v-show="scope.row.status === 1">停用
          </el-button>
          <el-button link type="primary" icon="Promotion" @click="handleStatus(scope.row)" v-hasPermi="['ai:aiApps:release']"
                     v-show="scope.row.status !== 1">发布
          </el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['ai:aiApps:remove']"
                     v-show="scope.row.status !== 1">删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
        v-show="total>0"
        :total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        @pagination="getList"
    />

    <!-- 添加或修改AI应用对话框 -->
    <el-dialog :title="title" v-model="open" fullscreen append-to-body destroy-on-close @close="handleAppClose">
      <el-row>
        <el-col :span="12" style="height: 90vh;overflow:  auto; padding: 15px 15px">
          <div>
            <el-form ref="aiAppsRef" :model="form" :rules="rules" label-width="120px">
              <el-form-item label="应用图标" prop="imgUrl">
                <image-upload v-model="form.imgUrl" limit="1"/>
              </el-form-item>
              <el-form-item label="应用名称" prop="name">
                <el-input v-model="form.name" placeholder="请输入应用名称"/>
              </el-form-item>
              <el-form-item label="工作流程" prop="workflowId">
                <el-select v-model="form.workflowId" placeholder="请选择工作流程" clearable fit-input-width @change="handleSelectWorkflow">
                  <el-option
                      v-for="item in aiWorkflowList"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="模型" prop="modelId" v-show="showSelectModel">
                <el-select v-model="form.modelId" placeholder="请选择模型" clearable fit-input-width @change="handleSelectModel">
                  <el-option
                      v-for="item in aiModelList"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="提示词" prop="prompt" v-show="showSelectModel">
                <el-input v-model="form.prompt" type="textarea" rows="10" placeholder="请输入内容" @change="initPreviewReqData"/>
              </el-form-item>
              <el-form-item label="对话提示语" prop="userTips">
                <el-input v-model="form.userTips" type="textarea" rows="5" placeholder="请输入用户提示语，每行代表一条提示语"/>
              </el-form-item>
              <el-form-item label="max_tokens" prop="maxTokens" v-show="showSelectModel">
                <el-slider v-model="form.maxTokens" :max="8190" :min="1" show-input @change="initPreviewReqData"/>
              </el-form-item>
              <el-form-item label="temperature" prop="temperature" v-show="showSelectModel">
                <el-slider v-model="form.temperature" :max="2.0" :min="0" show-input :step="0.1" @change="initPreviewReqData"/>
              </el-form-item>
              <el-form-item label="top_p" prop="topP" v-show="showSelectModel">
                <el-slider v-model="form.topP" :max="1.0" :min="0.1" show-input :step="0.1" @change="initPreviewReqData"/>
              </el-form-item>
              <el-form-item label="top_k" prop="topK" v-show="showSelectModel">
                <el-slider v-model="form.topK" :max="100" :min="0" show-input @change="initPreviewReqData"/>
              </el-form-item>
              <el-form-item label="知识库" prop="knowledgeId" v-show="showSelectModel">
                <el-select v-model="form.knowledgeId" placeholder="请选择知识库" clearable fit-input-width @change="handleSelectKnowledge">
                  <el-option
                      v-for="item in aiKnowledgeList"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id"
                  />
                </el-select>
              </el-form-item>

              <el-form-item label="LLM渲染知识库" prop="hasLlmRender" v-show="showSelectModel && showSelectKnowledge">
                <el-select v-model="form.hasLlmRender" placeholder="请选择知识库" fit-input-width @change="initPreviewReqData">
                  <el-option
                      v-for="item in sys_yes_no"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                  />
                </el-select>
              </el-form-item>
            </el-form>
            <div class="dialog-footer" style="text-align: right">
              <el-button type="primary" @click="submitFormStore">暂 存</el-button>
              <el-button type="primary" @click="submitForm">发 布</el-button>
              <el-button @click="cancel">取 消</el-button>
            </div>
          </div>

        </el-col>
        <el-col :span="12">
          <div class="aiApp-container">
            <el-container>
              <el-aside width="280px" v-show="!isPreviewFlag">
                <Sidebar/>
              </el-aside>
              <el-main>
                <ChatArea/>
              </el-main>
            </el-container>
          </div>
        </el-col>
      </el-row>
    </el-dialog>

    <el-dialog :title="title" v-model="detailOpen" fullscreen append-to-body destroy-on-close @close="handleAppClose">
      <el-row>
        <el-col :span="12" style="height: 90vh;overflow:  auto; padding: 15px 15px">
          <div>
            <el-form ref="aiAppsRef" :model="form" :rules="rules" label-width="120px">
              <el-form-item label="应用图标" prop="imgUrl">
                <image-upload v-model="form.imgUrl" limit="1" disabled/>
              </el-form-item>
              <el-form-item label="应用名称" prop="name">
                <el-input v-model="form.name" placeholder="请输入应用名称" disabled/>
              </el-form-item>
              <el-form-item label="工作流程" prop="workflowId">
                <el-select v-model="form.workflowId" placeholder="请选择工作流程" clearable fit-input-width @change="handleSelectWorkflow" disabled>
                  <el-option
                      v-for="item in aiWorkflowList"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="模型" prop="modelId" v-show="showSelectModel">
                <el-select v-model="form.modelId" placeholder="请选择模型" clearable fit-input-width @change="handleSelectModel" disabled>
                  <el-option
                      v-for="item in aiModelList"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id"
                  />
                </el-select>
              </el-form-item>
              <el-form-item label="提示词" prop="prompt" v-show="showSelectModel">
                <el-input v-model="form.prompt" type="textarea" rows="10" placeholder="请输入内容" disabled/>
              </el-form-item>
              <el-form-item label="对话提示语" prop="userTips">
                <el-input v-model="form.userTips" type="textarea" rows="5" placeholder="请输入用户提示语，每行代表一条提示语" disabled/>
              </el-form-item>
              <el-form-item label="max_tokens" prop="maxTokens" v-show="showSelectModel">
                <el-slider v-model="form.maxTokens" :max="8190" :min="1" show-input disabled/>
              </el-form-item>
              <el-form-item label="temperature" prop="temperature" v-show="showSelectModel">
                <el-slider v-model="form.temperature" :max="2.0" :min="0" show-input :step="0.1" disabled/>
              </el-form-item>
              <el-form-item label="top_p" prop="topP" v-show="showSelectModel">
                <el-slider v-model="form.topP" :max="1.0" :min="0.1" show-input :step="0.1" disabled/>
              </el-form-item>
              <el-form-item label="top_k" prop="topK" v-show="showSelectModel">
                <el-slider v-model="form.topK" :max="100" :min="0" show-input disabled/>
              </el-form-item>
              <el-form-item label="知识库" prop="knowledgeId" v-show="showSelectModel">
                <el-select v-model="form.knowledgeId" placeholder="请选择知识库" clearable fit-input-width @change="handleSelectKnowledge" disabled>
                  <el-option
                      v-for="item in aiKnowledgeList"
                      :key="item.id"
                      :label="item.name"
                      :value="item.id"
                  />
                </el-select>
              </el-form-item>

              <el-form-item label="LLM渲染知识库" prop="hasLlmRender" v-show="showSelectModel && showSelectKnowledge" disabled="">
                <el-select v-model="form.hasLlmRender" placeholder="请选择知识库" fit-input-width disabled>
                  <el-option
                      v-for="item in sys_yes_no"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                  />
                </el-select>
              </el-form-item>
            </el-form>
            <div class="dialog-footer" style="text-align: right">
              <el-button @click="cancel">取 消</el-button>
            </div>
          </div>

        </el-col>
        <el-col :span="12">
          <div class="aiApp-container">
            <el-container>
              <el-aside width="280px" v-show="!isPreviewFlag">
                <Sidebar/>
              </el-aside>
              <el-main>
                <ChatArea/>
              </el-main>
            </el-container>
          </div>
        </el-col>
      </el-row>
    </el-dialog>

    <el-drawer v-model="previewOpen" append-to-body destroy-on-close size="50%"
               @close="previewClose()"
               :close-on-click-modal="false"
               :close-on-press-escape="false"
               :show-close="canSendFlag"
               title="智能助手预览">
      <div class="aiApp-container">
        <el-container>
          <el-aside width="280px" v-show="!isPreviewFlag">
            <Sidebar/>
          </el-aside>
          <el-main>
            <ChatArea/>
          </el-main>
        </el-container>
      </div>
    </el-drawer>
  </div>
</template>

<script setup name="AiApps">
import {addAiApps, delAiApps, getAiApps, listAiApps, updateAiApps, updateStatus} from "@/api/ai/aiApps.js";
import {listAiEnableModel} from "@/api/ai/aiModel.js";
import {listAllCompleteKnowledge} from "@/api/ai/aiKnowledge.js";
import {
  aiAppId,
  canSelectModelFlag,
  canSendFlag, currentSelectType,
  initNewChat,
  isPreviewFlag,
  llmModelData,
  previewReqData,
  selectModel,
  selectWorkflow,
  workflowData
} from "@/api/ai/ai.js";
import ChatArea from "@/views/ai/chart/ChatArea.vue";
import Sidebar from "@/views/ai/chart/Sidebar.vue";
import {listAllRelease} from "@/api/ai/aiFlow.js";

const {proxy} = getCurrentInstance();
const {ai_apps_status, sys_yes_no} = proxy.useDict('ai_apps_status', 'sys_yes_no');

const aiAppsList = ref([]);
const open = ref(false);
const detailOpen = ref(false);
const previewOpen = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");
const aiModelList = ref([])
const aiKnowledgeList = ref([])
const aiWorkflowList = ref([])
const showSelectModel = ref(true)
const showSelectKnowledge = ref(false)

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    imgUrl: null,
    name: null,
    modelCode: null,
    modelName: null,
    prompt: null,
    knowledgeIds: null,
    status: null,
  },
  rules: {
    imgUrl: [
      {required: true, message: "应用图标不能为空", trigger: "blur"}
    ],
    name: [
      {required: true, message: "应用名称不能为空", trigger: "blur"}
    ],
    status: [
      {required: true, message: "状态 0：待发布 1：已发布不能为空", trigger: "change"}
    ],
  }
});

const {queryParams, form, rules} = toRefs(data);

function handleStatus(row) {
  const status = row.status
  if (status === 1) {
    // 停用
    // 确认停用框
    proxy.$modal.confirm('确认要停用"' + row.name + '"应用吗?').then(function () {
      updateStatus(row.id, -1).then(resp => {
        proxy.$modal.msgSuccess("停用成功")
        getList()
      })
    }).catch(function () {
    });
  } else {
    // 发布
    proxy.$modal.confirm('确认要发布"' + row.name + '"应用吗?').then(function () {
      updateStatus(row.id, 1).then(resp => {
        proxy.$modal.msgSuccess("发布成功")
        getList()
      })
    }).catch(function () {

    });

  }
}

function handlePreview(row) {
  reset();
  const _id = row.id || ids.value
  getAiApps(_id).then(response => {
    form.value = response.data;
    previewOpen.value = true;
    isPreviewFlag.value = true
    canSelectModelFlag.value = false
    selectModel.value = form.value.modelCode
    aiAppId.value = _id
    initNewChat()
  });
}

function previewClose() {
  isPreviewFlag.value = false
  selectModel.value = null
  aiAppId.value = null
  canSelectModelFlag.value = true
  initNewChat()
}

/** 查询AI应用列表 */
function getList() {
  loading.value = true;
  listAiApps(queryParams.value).then(response => {
    aiAppsList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  detailOpen.value = false;
  previewOpen.value = false;
  reset();
}

// 表单重置
function reset() {
  form.value = {
    id: null,
    imgUrl: null,
    name: null,
    workflowId: null,
    modelId: null,
    prompt: null,
    userTips: null,
    maxTokens: 512,
    temperature: 0.7,
    topP: 0.7,
    topK: 50,
    knowledgeId: null,
    hasLlmRender: null,
    status: null,
    createBy: null,
    createTime: null,
    updateBy: null,
    updateTime: null,
    remark: null
  };
  proxy.resetForm("aiAppsRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  initPreview()
  open.value = true;
  title.value = "添加AI应用";
}

// 详情按钮操作
function handleDetail(row) {
  reset();
  const _id = row.id || ids.value
  getAiApps(_id).then(response => {
    form.value = response.data;
    if (form.value.workflowId !== null) {
      handleSelectWorkflow()
      showSelectModel.value = false
    }
    if (form.value.modelId !== null) {
      showSelectModel.value = true
      handleSelectModel()
      handleSelectKnowledge()
    }
    initPreview()
    detailOpen.value = true;
    title.value = "AI应用详情";
  });
}


/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  const _id = row.id || ids.value
  getAiApps(_id).then(response => {
    form.value = response.data;
    if (form.value.workflowId !== null) {
      handleSelectWorkflow()
      currentSelectType.value = 'flowModel'
      showSelectModel.value = false
    }
    if (form.value.modelId !== null) {
      showSelectModel.value = true
      handleSelectModel()
      handleSelectKnowledge()
      currentSelectType.value = 'llmModel'
    }
    initPreview()
    open.value = true;
    title.value = "修改AI应用";
  });
}

function handleAppClose() {
  reset()
  isPreviewFlag.value = false
  canSelectModelFlag.value = true
  selectModel.value = null
  selectWorkflow.value = null
  aiAppId.value = null
  // workflowData.value = []
  // llmModelData.value = []
}

function initPreview() {
  isPreviewFlag.value = true
  canSelectModelFlag.value = false
  initPreviewReqData()
  selectModel.value = form.value.modelId
  if (form.value.workflowId) {
    selectWorkflow.value = form.value.workflowId
  }
  initNewChat()
}

function initPreviewReqData() {
  previewReqData.value = {
    prompts: form.value.prompt,
    maxTokens: form.value.maxTokens,
    temperature: form.value.temperature,
    topP: form.value.topP,
    topK: form.value.topK,
    knowledgeId: form.value.knowledgeId,
    hasLlmRender: form.value.hasLlmRender,
  }
}

function handleSelectWorkflow() {
  if (form.value.workflowId) {
    showSelectModel.value = false
  } else {
    showSelectModel.value = true
  }
  initPreviewReqData()
  selectWorkflow.value = form.value.workflowId
  currentSelectType.value = 'flowModel'
  // llmModelData.value = []
  // workflowData.value = []
  // workflowData.value.push({id: form.value.workflowId, name: getWorkflowName(form.value.workflowId)})
}

function handleSelectModel() {
  initPreviewReqData()
  selectWorkflow.value = null
  selectModel.value = form.value.modelId
  currentSelectType.value = 'llmModel'
  // workflowData.value = []
  // llmModelData.value = []
  // llmModelData.value.push({id: form.value.modelId, name: getModelName(form.value.modelId)})
}

function handleSelectKnowledge() {
  initPreviewReqData()
  if (form.value.knowledgeId) {
    form.value.hasLlmRender = "N"
    showSelectKnowledge.value = true
  } else {
    showSelectKnowledge.value = false
  }
}


/** 提交按钮 */
function submitForm() {
  form.value.status = 1
  submitData();
}

function submitData() {
  proxy.$refs["aiAppsRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateAiApps(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addAiApps(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

function submitFormStore() {
  form.value.status = 0
  submitData();
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value;
  proxy.$modal.confirm('是否确认删除AI应用编号为"' + _ids + '"的数据项？').then(function () {
    return delAiApps(_ids);
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {
  });
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download('ai/aiApps/export', {
    ...queryParams.value
  }, `aiApps_${new Date().getTime()}.xlsx`)
}

function initAiModel() {
  const queryType = [0]
  listAiEnableModel(queryType).then(response => {
    aiModelList.value = response.data;
  })
}

function getModelName(modelId) {
  const model = aiModelList.value.find(item => item.id === modelId)
  return model ? model.name : ''
}

function initKnowledge() {
  listAllCompleteKnowledge().then(response => {
    aiKnowledgeList.value = response.data;
  })
}

function initWorkflow() {
  listAllRelease().then(response => {
    aiWorkflowList.value = response.data;
  })
}

function getWorkflowName(fId) {
  const workflow = aiWorkflowList.value.find(item => item.id === fId)
  return workflow ? "流程【" + workflow.name + "】" : ''
}

getList();
initAiModel();
initKnowledge();
initWorkflow();
</script>

<style scoped>
.aiApp-container {
  height: 87vh;
  display: flex;
  padding: 0 0 !important;
}

.el-container {
  height: 100%;
}

.el-aside {
  background-color: #f5f7fa;
  border-right: 1px solid #e6e6e6;
  margin-bottom: 0;
}

.el-main {
  padding: 0;
  background-color: #fff;
}
</style>
